package guda.house.biz.impl;

import java.util.*;

import guda.house.biz.beans.vo.OwnerVO;
import guda.house.biz.constants.CommonResultCode;
import guda.house.biz.enums.BooleanEnum;
import guda.house.biz.enums.SysVarTypeEnum;
import guda.house.biz.form.bill.InvoiceLogEditForm;
import guda.house.biz.form.bill.InvoiceLogForm;
import guda.house.biz.form.bill.InvoiceLogReverseForm;
import guda.house.biz.query.*;
import guda.house.biz.util.PriceUtil;
import guda.house.biz.util.Transform;
import guda.house.biz.util.TransformHelper;
import guda.house.dal.dao.*;
import guda.house.dal.dataobject.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import guda.house.biz.InvoiceLogBiz;
import guda.grape.autogen.common.page.BaseQuery;
import guda.grape.autogen.common.page.BizResult;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;

public class InvoiceLogBizImpl implements InvoiceLogBiz {

    private final static Logger logger = LoggerFactory.getLogger(InvoiceLogBizImpl.class);

    @Autowired
    private InvoiceLogDAO invoiceLogDAO;
    @Autowired
    private SysVarDAO sysVarDAO;
    @Autowired
    private OwnerDAO ownerDAO;
    @Autowired
    private BuildingDAO buildingDAO;
    @Autowired
    private UnitDAO unitDAO;
    @Autowired
    private SuiteDAO suiteDAO;
    @Autowired
    private BillPayDAO billPayDAO;
    @Autowired
    private VillageDAO villageDAO;

    @Autowired
    private TransactionTemplate transactionTemplate;

    public BizResult detail(long id) {
        BizResult bizResult = new BizResult();
        try {
            InvoiceLogDO invoiceLogDO = invoiceLogDAO.getInvoiceLogById(id);
            bizResult.data.put("invoiceLogDO", invoiceLogDO);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("query InvoiceLog error", e);
        }
        return bizResult;
    }

    public BizResult list(InvoiceLogQuery invoiceLogQuery) {
        BizResult bizResult = new BizResult();
        List<Long> idList = null;
        if(StringUtils.hasText(invoiceLogQuery.getOwnerName())) {
            OwnerQuery ownerQuery = new OwnerQuery();
            ownerQuery.setOwnerName(invoiceLogQuery.getOwnerName());
            List<OwnerDO> ownerDOs = ownerDAO.selectForPage(ownerQuery);
            if(ownerDOs.size()>0){
                Set<Long> idSet = TransformHelper.transform2Set(ownerDOs, new Transform<OwnerDO, Long>() {
                    @Override
                    public Long transform(OwnerDO object) {
                        return object.getSuiteId();
                    }
                });
                idList = new ArrayList<Long>(idSet);
            }
        }
        try {
            if(invoiceLogQuery.getVillageId()!=null){
                BuildingQuery buildingQuery = new BuildingQuery();
                buildingQuery.setPageSize(10000);
                buildingQuery.setVillageId(invoiceLogQuery.getVillageId());

                List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
                buildingQuery.setPageSize(10000);
                List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
                    @Override
                    public Long transform(BuildingDO object) {
                        return object.getBuildingId();
                    }
                });

                UnitQuery unitQuery = new UnitQuery();
                unitQuery.setBuildingIdList(buildingIdList);
                unitQuery.setPageSize(10000);
                List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
                List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                    @Override
                    public Long transform(UnitDO object) {
                        return object.getUnitId();
                    }
                });
                SuiteQuery suiteQuery = new SuiteQuery();
                suiteQuery.setPageSize(10000);
                suiteQuery.setUnitIdList(unitIdList);
                if(idList!=null){
                    suiteQuery.setSuiteIdList(idList);
                }
                List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
                List<Long> suiteIdList = TransformHelper.transform(suiteDOs, new Transform<SuiteDO, Long>() {
                    @Override
                    public Long transform(SuiteDO object) {
                        return object.getSuiteId();
                    }
                });
                invoiceLogQuery.setSuiteIdList(suiteIdList);
            }
            int totalCount = invoiceLogDAO.countForPage(invoiceLogQuery);
            invoiceLogQuery.setTotalCount(totalCount);
            List<InvoiceLogDO> invoiceLogList = invoiceLogDAO.selectForPage(invoiceLogQuery);
            bizResult.data.put("invoiceLogList", invoiceLogList);
            bizResult.data.put("query", invoiceLogQuery);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("view InvoiceLog list error", e);
        }
        return bizResult;
    }

    public BizResult delete(long id) {
        BizResult bizResult = new BizResult();
        try {
            invoiceLogDAO.delInvoiceLogById(id);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("delete invoiceLog error", e);
        }
        return bizResult;
    }

    public BizResult create(InvoiceLogForm invoiceLogForm) {
        final BizResult bizResult = new BizResult();
        final InvoiceLogDO invoiceLogDO = invoiceLogForm.toDO();
        String payIdArray = invoiceLogForm.getPayIdArray();
        final String[] split = payIdArray.split(",");
        if (split.length == 0) {
            bizResult.code = CommonResultCode.PARAM_MISS;
            return bizResult;
        }
        try {
            SysVarDO sysVarById = sysVarDAO.getSysVarById(invoiceLogDO.getInvoiceCatId());
            if (sysVarById == null) {
                bizResult.code = CommonResultCode.RECORD_NOT_FOUND;
                return bizResult;
            }
            invoiceLogDO.setInvoiceCat(sysVarById.getVarValue());

            SysVarDO invoiceSysVarById = sysVarDAO.getSysVarById(invoiceLogDO.getInvoiceTypeId());
            if (sysVarById == null) {
                bizResult.code = CommonResultCode.RECORD_NOT_FOUND;
                return bizResult;
            }
            invoiceLogDO.setInvoiceType(invoiceSysVarById.getVarValue());

            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                    long id = invoiceLogDAO.insert(invoiceLogDO);
                    for (String s : split) {
                        Long billPayId = Long.parseLong(s);
                        BillPayDO billPayById = billPayDAO.getBillPayById(billPayId);
                        BillPayDO temp = new BillPayDO();
                        temp.setPayId(billPayById.getPayId());
                        temp.setInvoiceId(id);
                        billPayDAO.updateByIdSelective(temp);

                    }
                    bizResult.data.put("id", id);
                }
            });


            bizResult.success = true;
        } catch (Exception e) {
            logger.error("create InvoiceLog error", e);
        }
        return bizResult;
    }

    @Override
    public BizResult update(InvoiceLogEditForm invoiceLogEditForm) {
        BizResult bizResult = new BizResult();
        final InvoiceLogDO invoiceLogDO = invoiceLogEditForm.toDO();
        try {
            SysVarDO sysVarById = sysVarDAO.getSysVarById(invoiceLogDO.getInvoiceCatId());
            if (sysVarById == null) {
                bizResult.code = CommonResultCode.RECORD_NOT_FOUND;
                return bizResult;
            }
            invoiceLogDO.setInvoiceCat(sysVarById.getVarValue());

            SysVarDO invoiceSysVarById = sysVarDAO.getSysVarById(invoiceLogDO.getInvoiceTypeId());
            if (sysVarById == null) {
                bizResult.code = CommonResultCode.RECORD_NOT_FOUND;
                return bizResult;
            }
            final String[] split = invoiceLogEditForm.getPayIdArray().split(",");
            if (split.length == 0) {
                bizResult.code = CommonResultCode.PARAM_MISS;
                return bizResult;
            }
            invoiceLogDO.setInvoiceType(invoiceSysVarById.getVarValue());
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                    invoiceLogDAO.updateByIdSelective(invoiceLogDO);
                    for (String s : split) {
                        Long billPayId = Long.parseLong(s);
                        BillPayDO billPayById = billPayDAO.getBillPayById(billPayId);
                        BillPayDO temp = new BillPayDO();
                        temp.setPayId(billPayById.getPayId());
                        temp.setInvoiceId(invoiceLogDO.getLogId());
                        billPayDAO.updateByIdSelective(temp);
                    }
                }
            });

            bizResult.success = true;
        } catch (Exception e) {
            logger.error("update InvoiceLog error", e);
        }
        return bizResult;
    }

    @Override
    public BizResult queryForCreate(InvoiceLogForm invoiceLogForm) {
        BizResult bizResult = new BizResult();
        String payIdArray = invoiceLogForm.getPayIdArray();
        String[] split = payIdArray.split(",");
        if (split.length == 0) {
            bizResult.code = CommonResultCode.PARAM_MISS;
            return bizResult;
        }
        List<BillPayDO> billPayDOList = new ArrayList<BillPayDO>();
        long money = 0;
        String comment = "";
        for (int i = 0, len = split.length; i < len; ++i) {
            Long payId = Long.parseLong(split[i]);
            BillPayDO billPayById = billPayDAO.getBillPayById(payId);
            if (billPayById != null) {
                billPayDOList.add(billPayById);
                money = money + billPayById.getPayTotal();
                if (billPayById.getPayDesc() != null) {
                    comment = comment + billPayById.getPayDesc() + " ";
                }
            }
        }
        invoiceLogForm.setInvoiceComment(comment);
        invoiceLogForm.setInvoiceMoney(PriceUtil.formatCNYNoGroup(money));
        OwnerVO ownerVO = new OwnerVO();
        BillPayDO billPayDO = billPayDOList.get(0);
        SuiteDO suiteById = suiteDAO.getSuiteById(billPayDO.getSuiteId());
        ownerVO.setSuiteDO(suiteById);
        UnitDO unitById = unitDAO.getUnitById(suiteById.getUnitId());
        ownerVO.setUnitDO(unitById);
        BuildingDO buildingById = buildingDAO.getBuildingById(unitById.getBuildingId());
        ownerVO.setBuildingDO(buildingById);
        VillageDO villageById = villageDAO.getVillageById(buildingById.getVillageId());
        ownerVO.setVillageDO(villageById);
        OwnerQuery ownerQuery = new OwnerQuery();
        ownerQuery.setSuiteId(suiteById.getSuiteId());
        List<OwnerDO> ownerDOs = ownerDAO.selectForPage(ownerQuery);
        ownerVO.setOwnerDOList(ownerDOs);
        bizResult.data.put("ownerVO", ownerVO);

        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setVillageId(villageById.getVillageId());
        sysVarQuery.setVarType(SysVarTypeEnum.invoice_cat.name());
        sysVarQuery.setPageSize(500);
        List<SysVarDO> invoiceCatList = sysVarDAO.selectForPage(sysVarQuery);
        bizResult.data.put("invoiceCatList", invoiceCatList);
        //查询所有楼栋
        sysVarQuery.setVarType(SysVarTypeEnum.invoice.name());
        List<SysVarDO> invoiceList = sysVarDAO.selectForPage(sysVarQuery);
        bizResult.data.put("invoiceList", invoiceList);
        bizResult.success = true;
        return bizResult;
    }


    public BizResult queryForEdit(InvoiceLogEditForm invoiceLogEditForm) {
        BizResult bizResult = new BizResult();
        InvoiceLogDO invoiceLogById = invoiceLogDAO.getInvoiceLogById(invoiceLogEditForm.getLogId());
        invoiceLogEditForm.initForm(invoiceLogById);
        List<BillPayDO> byInvoiceId = billPayDAO.getByInvoiceId(invoiceLogEditForm.getLogId());

        StringBuilder buf = new StringBuilder();
        for (BillPayDO billPayDO : byInvoiceId) {
            buf.append(billPayDO.getPayId()).append(",");
        }
        invoiceLogEditForm.setPayIdArray(buf.toString());

        OwnerVO ownerVO = new OwnerVO();
        SuiteDO suiteById = suiteDAO.getSuiteById(invoiceLogById.getSuiteId());
        ownerVO.setSuiteDO(suiteById);
        UnitDO unitById = unitDAO.getUnitById(suiteById.getUnitId());
        ownerVO.setUnitDO(unitById);
        BuildingDO buildingById = buildingDAO.getBuildingById(unitById.getBuildingId());
        ownerVO.setBuildingDO(buildingById);
        VillageDO villageById = villageDAO.getVillageById(buildingById.getVillageId());
        ownerVO.setVillageDO(villageById);
        OwnerQuery ownerQuery = new OwnerQuery();
        ownerQuery.setSuiteId(suiteById.getSuiteId());
        List<OwnerDO> ownerDOs = ownerDAO.selectForPage(ownerQuery);
        ownerVO.setOwnerDOList(ownerDOs);
        bizResult.data.put("ownerVO", ownerVO);

        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setVillageId(villageById.getVillageId());
        sysVarQuery.setVarType(SysVarTypeEnum.invoice_cat.name());
        sysVarQuery.setPageSize(500);
        List<SysVarDO> invoiceCatList = sysVarDAO.selectForPage(sysVarQuery);
        bizResult.data.put("invoiceCatList", invoiceCatList);
        //查询所有楼栋
        sysVarQuery.setVarType(SysVarTypeEnum.invoice.name());
        List<SysVarDO> invoiceList = sysVarDAO.selectForPage(sysVarQuery);
        bizResult.data.put("invoiceList", invoiceList);


        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult queryForReverse(Long logId) {
        BizResult bizResult = new BizResult();
        InvoiceLogDO invoiceLogById = invoiceLogDAO.getInvoiceLogById(logId);
        bizResult.data.put("invoiceLogDO", invoiceLogById);
        OwnerVO ownerVO = new OwnerVO();
        SuiteDO suiteById = suiteDAO.getSuiteById(invoiceLogById.getSuiteId());
        ownerVO.setSuiteDO(suiteById);
        UnitDO unitById = unitDAO.getUnitById(suiteById.getUnitId());
        ownerVO.setUnitDO(unitById);
        BuildingDO buildingById = buildingDAO.getBuildingById(unitById.getBuildingId());
        ownerVO.setBuildingDO(buildingById);
        VillageDO villageById = villageDAO.getVillageById(buildingById.getVillageId());
        ownerVO.setVillageDO(villageById);
        OwnerQuery ownerQuery = new OwnerQuery();
        ownerQuery.setSuiteId(suiteById.getSuiteId());
        List<OwnerDO> ownerDOs = ownerDAO.selectForPage(ownerQuery);
        ownerVO.setOwnerDOList(ownerDOs);
        bizResult.data.put("ownerVO", ownerVO);

        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setVillageId(villageById.getVillageId());
        sysVarQuery.setVarType(SysVarTypeEnum.invoice_cat.name());
        sysVarQuery.setPageSize(500);
        List<SysVarDO> invoiceCatList = sysVarDAO.selectForPage(sysVarQuery);
        bizResult.data.put("invoiceCatList", invoiceCatList);
        //查询所有楼栋
        sysVarQuery.setVarType(SysVarTypeEnum.invoice.name());
        List<SysVarDO> invoiceList = sysVarDAO.selectForPage(sysVarQuery);
        bizResult.data.put("invoiceList", invoiceList);


        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult reverse(final InvoiceLogReverseForm invoiceLogReverseForm) {
        BizResult bizResult = new BizResult();
        final InvoiceLogDO invoiceLogById = invoiceLogDAO.getInvoiceLogById(invoiceLogReverseForm.getLogId());
        final List<BillPayDO> byInvoiceId = billPayDAO.getByInvoiceId(invoiceLogReverseForm.getLogId());
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                InvoiceLogDO invoiceLogDO = new InvoiceLogDO();
                invoiceLogDO.setLogId(invoiceLogById.getLogId());
                invoiceLogDO.setOffsetComment(invoiceLogReverseForm.getOffsetComment());
                invoiceLogDO.setOffsetStatus(BooleanEnum.TRUE.getVal());
                invoiceLogDAO.updateByIdSelective(invoiceLogDO);
                for(BillPayDO billPayDO:byInvoiceId){
                    BillPayDO temp = new BillPayDO();
                    temp.setPayId(billPayDO.getPayId());
                    temp.setInvoiceId(0L);
                    billPayDAO.updateByIdSelective(temp);
                }
            }
        });
        bizResult.success = true;
        return bizResult;
    }


}
